package perms

import (
	"fmt"
	"github.com/gofiber/fiber/v2"
	"sg-backend/global"
	"sg-backend/model/user"
)

type _UserPermsForm struct {
	Checked   bool   `json:"checked"`
	Mid       uint   `json:"mid"`
	PermsType string `json:"permsType"`
	Uid       uint   `json:"uid"`
}

func UpdateUserPerm(ctx *fiber.Ctx) error {

	// 解释数据
	var dataDto _UserPermsForm
	if err := ctx.BodyParser(&dataDto); err != nil {
		return ctx.JSON(fiber.Map{
			"status":  "error",
			"message": fmt.Sprintf("数据解释出错！%s", err),
		})
	}

	// 数据获取成功
	// 开始设置权限
	// 权限为树级菜单，当拥有了上层的权限，则应自动拥有下层的权限
	var allMenuId []uint
	subMenu := getSubMenuId(dataDto.Mid)
	allMenuId = append(allMenuId, dataDto.Mid)
	allMenuId = append(allMenuId, subMenu...)

	// 1，处理读权限
	if dataDto.PermsType == "read" {
		for _, v := range allMenuId {

			// 判断权限是否存在
			var permsObj []user.Perms
			r := global.DB.
				Where("user_id = ? AND menu_id = ? AND type = ?", dataDto.Uid, v, "read").
				Find(&permsObj)

			if r.Error != nil {
				return ctx.JSON(fiber.Map{
					"status":  "error",
					"message": fmt.Sprintf("从数据库中解释权限出错！%s", r.Error),
				})
			}

			// 新增权限
			if dataDto.Checked {

				// 如果没设置，那么可以设置
				if r.RowsAffected == 0 {
					newPerm := user.Perms{
						MenuId: v,
						Type:   dataDto.PermsType,
						UserId: dataDto.Uid,
					}
					cr := global.DB.Create(&newPerm)
					if cr.Error != nil {
						return ctx.JSON(fiber.Map{
							"status":  "error",
							"message": fmt.Sprintf("保存权限到数据库出错！%s", cr.Error),
						})
					}
				}
			} else {

				// 删除权限
				// 只读权限删除时，需要连同高级权限一起删除
				global.DB.Where("user_id = ? AND menu_id = ? AND type = ?", dataDto.Uid, v, "read").
					Delete(&user.Perms{})
				global.DB.Where("user_id = ? AND menu_id = ? AND type = ?", dataDto.Uid, v, "add").
					Delete(&user.Perms{})
				global.DB.Where("user_id = ? AND menu_id = ? AND type = ?", dataDto.Uid, v, "update").
					Delete(&user.Perms{})
				global.DB.Where("user_id = ? AND menu_id = ? AND type = ?", dataDto.Uid, v, "delete").
					Delete(&user.Perms{})
			}

		}

	} else if dataDto.PermsType == "add" {

		// 2，新增权限，需要包含查看权限
		for _, v := range allMenuId {

			// 2.1 判断读权限是否存在
			var permsObj []user.Perms
			rr := global.DB.
				Where("user_id = ? AND menu_id = ? AND type = ?", dataDto.Uid, v, "read").
				Find(&permsObj)

			// 如果没设置，那么可以设置
			if rr.RowsAffected == 0 {
				newPerm := user.Perms{
					MenuId: v,
					Type:   "read",
					UserId: dataDto.Uid,
				}
				cr := global.DB.Create(&newPerm)
				if cr.Error != nil {
					return ctx.JSON(fiber.Map{
						"status":  "error",
						"message": fmt.Sprintf("保存权限到数据库出错！%s", cr.Error),
					})
				}
			}

			// 2.2 判断新增权限是否存在
			ra := global.DB.
				Where("user_id = ? AND menu_id = ? AND type = ?", dataDto.Uid, v, "add").
				Find(&permsObj)

			if ra.Error != nil {
				return ctx.JSON(fiber.Map{
					"status":  "error",
					"message": fmt.Sprintf("从数据库中解释权限出错！%s", ra.Error),
				})
			}

			// 如果没设置，那么可以设置
			if ra.RowsAffected == 0 {
				newPerm := user.Perms{
					MenuId: v,
					Type:   "add",
					UserId: dataDto.Uid,
				}
				cr := global.DB.Create(&newPerm)
				if cr.Error != nil {
					return ctx.JSON(fiber.Map{
						"status":  "error",
						"message": fmt.Sprintf("保存权限到数据库出错！%s", cr.Error),
					})
				}
			}

			// 删除权限
			if !dataDto.Checked {

				// 只删除本身的权限即可
				global.DB.Where("user_id = ? AND menu_id = ? AND type = ?", dataDto.Uid, v, "add").
					Delete(&user.Perms{})
			}

		}
	} else if dataDto.PermsType == "update" {

		// 3，修改权限，需要包含查看权限
		for _, v := range allMenuId {

			// 3.1 判断读权限是否存在
			var permsObj []user.Perms
			rr := global.DB.
				Where("user_id = ? AND menu_id = ? AND type = ?", dataDto.Uid, v, "read").
				Find(&permsObj)

			// 如果没设置，那么可以设置
			if rr.RowsAffected == 0 {
				newPerm := user.Perms{
					MenuId: v,
					Type:   "read",
					UserId: dataDto.Uid,
				}
				cr := global.DB.Create(&newPerm)
				if cr.Error != nil {
					return ctx.JSON(fiber.Map{
						"status":  "error",
						"message": fmt.Sprintf("保存权限到数据库出错！%s", cr.Error),
					})
				}
			}

			// 3.2 判断修改权限是否存在
			ru := global.DB.
				Where("user_id = ? AND menu_id = ? AND type = ?", dataDto.Uid, v, "update").
				Find(&permsObj)

			if ru.Error != nil {
				return ctx.JSON(fiber.Map{
					"status":  "error",
					"message": fmt.Sprintf("从数据库中解释权限出错！%s", ru.Error),
				})
			}

			// 如果没设置，那么可以设置
			if ru.RowsAffected == 0 {
				newPerm := user.Perms{
					MenuId: v,
					Type:   "update",
					UserId: dataDto.Uid,
				}
				cr := global.DB.Create(&newPerm)
				if cr.Error != nil {
					return ctx.JSON(fiber.Map{
						"status":  "error",
						"message": fmt.Sprintf("保存权限到数据库出错！%s", cr.Error),
					})
				}
			}

			// 删除权限
			if !dataDto.Checked {

				// 只删除本身的权限即可
				global.DB.Where("user_id = ? AND menu_id = ? AND type = ?", dataDto.Uid, v, "update").
					Delete(&user.Perms{})
			}

		}
	} else if dataDto.PermsType == "delete" {

		// 4，删除权限，需要包含查看权限
		for _, v := range allMenuId {

			// 4.1 判断读权限是否存在
			var permsObj []user.Perms
			rr := global.DB.
				Where("user_id = ? AND menu_id = ? AND type = ?", dataDto.Uid, v, "read").
				Find(&permsObj)

			// 如果没设置，那么可以设置
			if rr.RowsAffected == 0 {
				newPerm := user.Perms{
					MenuId: v,
					Type:   "read",
					UserId: dataDto.Uid,
				}
				cr := global.DB.Create(&newPerm)
				if cr.Error != nil {
					return ctx.JSON(fiber.Map{
						"status":  "error",
						"message": fmt.Sprintf("保存权限到数据库出错！%s", cr.Error),
					})
				}
			}

			// 4.2 判断修改权限是否存在
			rd := global.DB.
				Where("user_id = ? AND menu_id = ? AND type = ?", dataDto.Uid, v, "delete").
				Find(&permsObj)

			if rd.Error != nil {
				return ctx.JSON(fiber.Map{
					"status":  "error",
					"message": fmt.Sprintf("从数据库中解释权限出错！%s", rd.Error),
				})
			}

			// 如果没设置，那么可以设置
			if rd.RowsAffected == 0 {
				newPerm := user.Perms{
					MenuId: v,
					Type:   "delete",
					UserId: dataDto.Uid,
				}
				cr := global.DB.Create(&newPerm)
				if cr.Error != nil {
					return ctx.JSON(fiber.Map{
						"status":  "error",
						"message": fmt.Sprintf("保存权限到数据库出错！%s", cr.Error),
					})
				}
			}

			// 删除权限
			if !dataDto.Checked {

				// 只删除本身的权限即可
				global.DB.Where("user_id = ? AND menu_id = ? AND type = ?", dataDto.Uid, v, "delete").
					Delete(&user.Perms{})
			}

		}
	}

	// 返回结果
	return ctx.JSON(fiber.Map{
		"status":  "done",
		"message": "设置成功！",
	})
}

func getSubMenuId(menuId uint) []uint {
	var menuIdList []uint

	// 获取子级
	var menuList []user.Menu
	global.DB.Where("pid = ?", menuId).Find(&menuList)

	for _, v := range menuList {
		menuIdList = append(menuIdList, v.Id)
		subMenuData := getSubMenuId(v.Id)
		if len(subMenuData) > 0 {
			menuIdList = append(menuIdList, subMenuData...)
		} else {
			menuIdList = append(menuIdList, v.Id)
		}
	}
	return menuIdList
}
